#include <iostream>
#include <string>
#include <any>
class Any
{
private:
    class holders
    {
    public:
        virtual ~holders() {};
        virtual holders *clone() = 0;
        virtual const std::type_info &type() = 0;
    };
    template <class T>
    class placeholders : public holders
    {
    public:
        placeholders(const T &val)
            : _val(val) {}
        ~placeholders() {}
        virtual holders *clone()
        {
            return new placeholders(_val);
        }
        virtual const std::type_info &type()
        {
            return typeid(T);
        }

        T _val;
    };

public:
    holders *_content;

private:
    Any &swap(Any &other)
    {
        std::swap(other, *this);
        return *this;
    }

public:
    // 构造
    Any() : _content(nullptr) {};
    template <class T>
    Any(const T &val)
    {
        _content = new placeholders<T>(val);
    }
    // 析构
    ~Any()
    {
        if (_content)
            delete _content;
    }
    // 拷贝构造
    Any(const Any &other)
    {
        // 如果otehr不为空，那就可以拷贝，注意不能是浅拷贝，所以才设计了一个clone函数
        _content = other._content ? other._content->clone() : nullptr;
    }
    // 赋值运算符重载
    template <class T>
    Any &operator=(const T &val)
    {
        Any(val).swap(*this);
        return *this;
    };
    template <class T>
    Any &operator=(const Any &other)
    {
        Any(other).swap(*this);
        return *this;
    };

    // 获取子类对象中数据的指针
    template <class T>
    T *GetPtr()
    {
        return &(((placeholders<T> *)_content)->_val);
    }
};
class Test
{
public:
    Test() { std::cout << "构造" << std::endl; }
    Test(const Test &t) { std::cout << "拷贝构造" << std::endl; }
    ~Test() { std::cout << "析构" << std::endl; }
};

int main()
{
    // std::any a;
    // a = 10;
    // int *pa = std::any_cast<int>(&a);
    // std::cout << *pa << std::endl;

    // 测试自己写的any类
    //  Any a;
    //  {
    //      Test t;
    //      a = t;
    //  }
    //  a=10;
    //  int *pa = a.GetPtr<int>();
    //  std::cout << *pa << std::endl;

    // a = std::string("hello");
    // std::string *ps = a.GetPtr<std::string>();
    // std::cout << *ps << std::endl;
    return 0;
}